﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;

namespace ZealandIT.MsbuildTasks.IO
{
    /// <summary>
    /// Creates an ordered file list based on a wildcard file mask. This list
    /// is returned as an ITaskItem array.
    /// Allows ascending/descending ordering by filename, date created
    /// or date modified.
    /// </summary>
    public class OrderedFileList : Task
    {
        private string _folder;
        private string[] _wildCards;
        private ITaskItem[] _files;
        private List<FileInfo> _fileList;
        private bool _recurse=false;
        private SortDirection _orderDirection=SortDirection.Ascending;
        private SortAttribute _orderBy = SortAttribute.Filename;

        [Required]
        public string Folder
        {
            get { return _folder; }
            set { _folder = value; }
        }

        [Required]
        public string[] WildCards
        {
            get { return _wildCards; }
            set { _wildCards = value; }
        }

        public SortDirection OrderDirection
        {
            get { return _orderDirection; }
            set { _orderDirection = value; }
        }

        public SortAttribute OrderBy
        {
            get { return _orderBy; }
            set { _orderBy = value; }
        }

        public bool Recurse
        {
            get { return _recurse; }
            set { _recurse = value; }
        }
        
        [Output]
        public ITaskItem[] Files
        {
            get { return _files; }
            set { _files = value; }
        }

        public override bool Execute()
        {
            DirectoryInfo di = new DirectoryInfo(this._folder);
            _fileList = new List<FileInfo>(50);

            try
            {
                foreach (string wildcard in this._wildCards)
                {
                    foreach (FileInfo finfo in di.GetFiles(wildcard))
                    {
                        this._fileList.Add(finfo);
                    }
                }

                this._fileList.Sort(delegate(FileInfo f1, FileInfo f2)
                                    {
                                        switch (this.OrderBy)
                                        {
                                            case SortAttribute.Filename:
                                                return (this.OrderDirection == SortDirection.Ascending) ?
                                                            f1.Name.CompareTo(f2.Name) : f2.Name.CompareTo(f1.Name);
                                            case SortAttribute.DateCreated:
                                                return (this.OrderDirection == SortDirection.Ascending) ?
                                                    f1.CreationTime.CompareTo(f2.CreationTime) : f2.CreationTime.CompareTo(f1.CreationTime);
                                            case SortAttribute.DateModified:
                                                return (this.OrderDirection == SortDirection.Ascending) ?
                                                    f1.LastWriteTime.CompareTo(f2.LastWriteTime) : f2.LastWriteTime.CompareTo(f1.LastWriteTime);
                                            default:
                                                return (this.OrderDirection == SortDirection.Ascending) ?
                                                            f1.Name.CompareTo(f2.Name) : f2.Name.CompareTo(f1.Name);
                                        }

                                    });

                _files = new ITaskItem[this._fileList.Count];
                for (int i = 0; i < this._fileList.Count; i++)
                {
                    FileInfo fi = _fileList[i];
                    _files[i] = new TaskItem(fi.FullName);
                }
                return true;
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex);
                return false;
            }
        }


        public enum SortDirection
        { 
            Ascending,
            Descending
        }

        public enum SortAttribute
        { 
            DateCreated,
            DateModified,
            Filename
        }
    }
}
